import 'package:flutter/material.dart';
import 'package:kq_flutter_core_widget/utils/ex/kq_ex.dart';
import 'package:kq_flutter_core_widget/utils/kq_screen_util.dart';
import 'package:kq_flutter_pad_widgets/resources/kq_pad_theme_colors.dart';
import 'package:kq_flutter_pad_widgets/widgets/coordMap/kq_pad_coord_map_entity.dart';

class KqPadCoordMapPainter extends CustomPainter {
  List<KqPadCoordMapEntity> entitys = [];

  // x每个区间份额，默认6份
  int lot;

  /// X轴刻度线数量
  double markLineNum;

  /// 选中的位置
  int? selectedIndex;

  /// 选中的折线图颜色
  Color? lineSelectedColor;

  /// 默认的折线图颜色
  Color? lineNormalColor;

  /// 绘制刻度文本时，外部自定义处理
  String Function(double text)? onDrawMarkText;

  KqPadCoordMapPainter({
    required this.entitys,
    this.lot = 6,
    this.markLineNum = 25,
    this.selectedIndex,
    this.lineSelectedColor,
    this.lineNormalColor,
    this.onDrawMarkText,
  });

  @override
  void paint(Canvas canvas, Size size) {
    if (size.width > 0 && size.height > 0 && entitys.isNotEmpty) {
      /// 第一个刻度值离顶部的距离
      double marginTop = 15;

      /// 底部类型名称的高度
      double typeNameHeight = 30;

      /// 刻度的宽度
      double startMarkWidth = 45;

      /// 刻度值的字体大小
      double markFontSize = 6.sp;

      /// 刻度线离底部的距离
      double lineMarginBottom = 10;

      /// 刻度线离顶部的距离
      double lineMarginTop = 5;

      /// 刻度宽度
      double markWidth = 10;

      /// 刻度值离右边刻度线的距离
      double markMarginRight = 10;

      ///最后一条刻度线离右边的距离
      double marginRight = 20;

      if (double.parse(entitys[0].maxValue) > 99) {
        startMarkWidth = 80;
      }

      /// 先算出第一个值的宽度
      KqPadCoordMapEntity firstEntity = entitys.first;

      double firstMax = double.parse(firstEntity.maxValue);
      TextSpan span = TextSpan(
          text: firstMax.toStringAsFixed(1),
          style: TextStyle(fontSize: markFontSize));
      TextPainter textPainter = TextPainter(
          text: span, textDirection: TextDirection.rtl, maxLines: 2);
      textPainter.layout(maxWidth: startMarkWidth);

      /// 第一个刻度值文本的宽度
      double firstMarkWidth = textPainter.width;

      /// 画布的宽度
      double canvasWidth =
          size.width - firstMarkWidth - marginRight - markMarginRight;

      List paths = [];
      List linePaints = [];
      List selectPath = [];

      double smallMarkY = (size.height -
              typeNameHeight -
              lineMarginBottom -
              marginTop * 2 -
              lineMarginTop) /
          (markLineNum - 1);
      String smallMarkYStr = smallMarkY.toStringAsFixed(1);
      smallMarkY = double.parse(smallMarkYStr);

      /// 区间的宽度
      double itemAreaCanvasWidth = entitys.length - 1 > 0
          ? canvasWidth / (entitys.length - 1)
          : canvasWidth;
      for (var i = 0; i < entitys.length; i++) {
        KqPadCoordMapEntity entity = entitys[i];

        /// 最大值
        double max = double.parse(entity.maxValue);

        /// 最小值
        double min = double.parse(entity.minValue);

        /// 每个区间值
        double avg = ((max - min) / ((markLineNum - 1) / lot).floor());

        /// 每个刻度的值
        double smallMarkValue = ((max - min) / (markLineNum - 1));

        /// Y坐标线的X坐标
        double lineX = firstMarkWidth +
            markMarginRight +
            markWidth +
            itemAreaCanvasWidth * i;

        /// 画竖线
        Paint paint = Paint()
          ..strokeWidth = 2
          ..isAntiAlias = true
          ..strokeCap = StrokeCap.square
          ..color = KqPadThemeColors.textBF;
        canvas.drawLine(
            Offset(lineX, lineMarginTop),
            Offset(lineX, size.height - typeNameHeight - lineMarginBottom),
            paint);

        for (var z = 0; z < markLineNum; z++) {
          Paint smallPaint = Paint()
            ..strokeWidth = 2
            ..isAntiAlias = true
            ..strokeCap = StrokeCap.square
            ..color = KqPadThemeColors.textBF;
          canvas.drawLine(
              Offset(lineX, smallMarkY * z + marginTop + lineMarginTop),
              Offset(lineX - markWidth,
                  smallMarkY * z + marginTop + lineMarginTop),
              smallPaint);
          if (z == 0 || z == markLineNum - 1 || z % lot == 0) {
            String mark = onDrawMarkText != null
                ? onDrawMarkText!.call(max)
                : max.toStringAsFixed(1);
            if (z == markLineNum - 1) {
              mark = onDrawMarkText != null
                  ? onDrawMarkText!.call(min)
                  : min.toStringAsFixed(1);
            } else if (z != 0) {
              mark = onDrawMarkText != null
                  ? onDrawMarkText!.call(max - (z / lot) * avg)
                  : (max - (z / lot) * avg).toStringAsFixed(1);
            }
            TextSpan span = TextSpan(
                text: mark,
                style: TextStyle(
                  fontSize: markFontSize,
                  color: KqPadThemeColors.text8C,
                ));
            TextPainter textPainter = TextPainter(
                text: span, textDirection: TextDirection.rtl, maxLines: 2);
            textPainter.layout(maxWidth: startMarkWidth);
            double textY = smallMarkY * z +
                marginTop +
                lineMarginTop -
                textPainter.height / 2;
            canvas.drawRect(
                Rect.fromLTWH(
                    lineX - markWidth - markMarginRight - textPainter.width,
                    textY,
                    textPainter.width,
                    textPainter.height),
                Paint()
                  ..style = PaintingStyle.stroke
                  ..color = KqPadThemeColors.bgTransparent);
            textPainter.paint(
                canvas,
                Offset(lineX - markWidth - markMarginRight - textPainter.width,
                    textY));
          }

          /// 底部文本
          TextSpan bottomSpan = TextSpan(
              text: entity.typeName,
              style: TextStyle(fontSize: 8.sp, color: KqPadThemeColors.text59));
          TextPainter bottomTextPainter = TextPainter(
            text: bottomSpan,
            textDirection: TextDirection.rtl,
          );
          bottomTextPainter.layout(minWidth: 10, maxWidth: itemAreaCanvasWidth);
          canvas.drawRect(
              Rect.fromLTWH(
                  i == 0
                      ? lineX
                      : i == entitys.length - 1
                          ? lineX - bottomTextPainter.width
                          : lineX - bottomTextPainter.width / 2,
                  size.height - typeNameHeight,
                  bottomTextPainter.width,
                  bottomTextPainter.height),
              Paint()
                ..style = PaintingStyle.stroke
                ..color = KqPadThemeColors.bgTransparent);
          bottomTextPainter.paint(
              canvas,
              Offset(
                  i == 0
                      ? lineX
                      : i == entitys.length - 1
                          ? lineX - bottomTextPainter.width
                          : lineX - bottomTextPainter.width / 2,
                  size.height - typeNameHeight));
        }

        if (i == 0) {
          /// 画折线图
          List<String> points = entity.points;

          if (points.isNotNullOrEmpty) {
            double x = lineX;
            double y = lineMarginTop;
            double initX = lineX;
            double initY = lineMarginTop;
            int pathIndex = 0;
            for (var j = 0; j < points.length; j++) {
              Color lineColor = KqPadThemeColors.bgBlack05;
              String pointStr = points[j];
              double point = double.parse(pointStr);
              if (point < min) {
                y = size.height - typeNameHeight - lineMarginBottom;
              } else if (point <= max) {
                double extendY = (max - point) / smallMarkValue;
                y = marginTop + lineMarginTop + extendY * smallMarkY;
              }
              if (selectedIndex != null && j == selectedIndex) {
                initX = x;
                initY = y;
                pathIndex = j;
              } else {
                final Paint linePaint = Paint()
                  ..color = lineNormalColor ?? lineColor
                  ..strokeWidth = 1
                  ..style = PaintingStyle.stroke
                  ..isAntiAlias = true;

                Path path = Path()..moveTo(x, y);
                paths.add({'path': path, 'index': j});
                linePaints.add(linePaint);
              }
            }
            if (selectedIndex != null && selectedIndex! < points.length) {
              final Paint linePaint = Paint()
                ..color = lineSelectedColor ?? KqPadThemeColors.bgBlue
                ..strokeWidth = 1.5
                ..style = PaintingStyle.stroke
                ..isAntiAlias = true;

              Path path = Path()..moveTo(initX, initY);
              paths.add({'path': path, 'index': pathIndex});
              linePaints.add(linePaint);
            }
          }
        }
      }
      for (var p = 0; p < paths.length; p++) {
        var obj = paths[p];
        Path path = obj['path'];
        int index = obj['index'];
        for (var j = 1; j < entitys.length; j++) {
          KqPadCoordMapEntity entity = entitys[j];
          double max = double.parse(entity.maxValue);
          double min = double.parse(entity.minValue);
          double smallMarkValue = ((max - min) / (markLineNum - 1));

          double lineX = firstMarkWidth +
              markMarginRight +
              markWidth +
              itemAreaCanvasWidth * j;

          for (var h = 0; h < entity.points.length; h++) {
            String pointStr = entity.points[h];
            double point = double.parse(pointStr);
            if (index == h) {
              double x = lineX;
              double y = lineMarginTop;

              if (point < min) {
                y = size.height - typeNameHeight - lineMarginBottom;
              } else if (point <= max) {
                double extendY = (max - point) / smallMarkValue;
                y = marginTop + lineMarginTop + extendY * smallMarkY;
              }

              if (selectedIndex != null && h == selectedIndex) {
                selectPath.add({'x': x, 'y': y});
              } else {
                path.lineTo(x, y);
              }
              break;
            }
          }
        }
      }
      if (selectedIndex != null) {
        var lastObj = paths[paths.length - 1];
        Path lastPath = lastObj['path'];
        for (var w = 0; w < selectPath.length; w++) {
          var ele = selectPath[w];
          lastPath.lineTo(ele['x'], ele['y']);
        }
      }
      for (var h = 0; h < paths.length; h++) {
        if (h < linePaints.length) {
          var obj = paths[h];
          Path path = obj['path'];
          canvas.drawPath(path, linePaints[h]);
        }
      }
    }
  }

  @override
  bool shouldRepaint(covariant KqPadCoordMapPainter oldDelegate) {
    return entitys != oldDelegate.entitys ||
        selectedIndex != oldDelegate.selectedIndex;
  }
}
